-module(iax2_encoder).
-compile(export_all).
-include("iax2_common.hrl").

encode_ie(#ie_protocol_ver{version=2}) ->
	IEnbr = element(2,lists:keyfind(ie_version,1,?IE_MAP)),
	Len = 2,
	<<IEnbr:8,Len:8,2:16>>;
encode_ie(#ie_called_number{called_number=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_called_number,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_calling_number{calling_number=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_calling_number,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_calling_ani{calling_ani=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_calling_ani,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_calling_name{calling_name=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_calling_name,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_called_context{called_context=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_called_context,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_username{username=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_username,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_language{language=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_language,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_dnid{dnid=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_dnid,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);


encode_ie(#ie_challenge{challenge=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_challenge,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_md5_result{md5_result=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_md5_result,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);


encode_ie(#ie_rsa_result{rsa_result=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_rsa_result,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_rdnis{rdnis=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_rdnis,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);
encode_ie(#ie_password{password=Num}) ->
	IEnbr = element(2,lists:keyfind(ie_password,1,?IE_MAP)),
	encode_utf_ie(IEnbr,Num);

encode_ie(#ie_callingpres{callingpres=allowed_not_screened}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 0);

encode_ie(#ie_callingpres{callingpres=allowed_passed_screen}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 1);

encode_ie(#ie_callingpres{callingpres=allowed_failed_screen}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 2);

encode_ie(#ie_callingpres{callingpres=allowed_newtwork_number}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 3);

encode_ie(#ie_callingpres{callingpres=prohibited_not_screened}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 16#20);
encode_ie(#ie_callingpres{callingpres=prohibited_passed_screened}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 16#21);
encode_ie(#ie_callingpres{callingpres=prohibited_fail_screened}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 16#22);
encode_ie(#ie_callingpres{callingpres=prohibited_network_number}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 16#23);
encode_ie(#ie_callingpres{callingpres=number_not_available}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 16#43);
encode_ie(_R=#ie_callingpres{}) ->
	IEnbr = element(2,lists:keyfind(ie_callingpres,1,?IE_MAP)),
	encode_num_ie(IEnbr, 0);
encode_ie(#ie_format{format=speex}) ->
	IEnbr = element(2,lists:keyfind(ie_format,1,?IE_MAP)),
	Val = 16#00000200,
	Len=4,
	<<IEnbr:8,Len:8,Val:32>>;
encode_ie(#ie_format{format=g_711_mu_law}) ->
	IEnbr = element(2,lists:keyfind(ie_format,1,?IE_MAP)),
	Val = 16#00000004,
	Len=4,
	<<IEnbr:8,Len:8,Val:32>>.


















encode_utf_ie(IEnbr,Value) when is_list(Value) ->
	Len = length(Value),
	BinVal=list_to_binary(Value),
	<<IEnbr:8,Len:8,BinVal/binary>>.


encode_num_ie(IEnbr,Value) when is_number(Value) ->
	BinVal = binary:encode_unsigned(Value),
	Len=erlang:byte_size(BinVal),
	<<IEnbr:8,Len:8,BinVal/binary>>.



encode_full_frame(#fullframe{srccallnumber=SrcCallNo,
					r=R,
					dstcallnumber=DstCallNo,
					timestamp=Ts,
					oseqno=OSeqNo,
					iseqno=ISeqNo,
					frametype=FT,
					c=C,
					subclass=Subclass,
					data=IEList}) when is_list(IEList)->
	IEBin = encode_ie_list(IEList),
	<<1:1,
					SrcCallNo:15,
					R:1,
					DstCallNo:15,
					Ts:32,
					OSeqNo:8,
					ISeqNo:8,
					FT:8,
					C:1,
					Subclass:7,IEBin/binary>>;

encode_full_frame(#fullframe{srccallnumber=SrcCallNo,
					r=R,
					dstcallnumber=DstCallNo,
					timestamp=Ts,
					oseqno=OSeqNo,
					iseqno=ISeqNo,
					frametype=FT,
					c=C,
					subclass=Subclass,
					data=Payload}) when is_binary(Payload)->
	
	<<1:1,
					SrcCallNo:15,
					R:1,
					DstCallNo:15,
					Ts:32,
					OSeqNo:8,
					ISeqNo:8,
					FT:8,
					C:1,
					Subclass:7,Payload/binary>>.



encode_ie_list([]) -> <<>>;
encode_ie_list(IEList) ->
		[H|T] = IEList,
		%io:format("Decode H= ~p T=~p  ~n",[H,T]),
		B = <<(encode_ie(H))/binary,(encode_ie_list(T))/binary>>,
		%io:format("So far we got ~p~n",[B]),
		B.




test() ->
	R=#ie_protocol_ver{version=2},
	io:format("R = ~p~n",[R]),
	encode_ie(R),
	io:format("~p~n",[encode_num_ie(12,31231312312)]),
	io:format("~p~n",[encode_ie(#ie_calling_number{calling_number="693595766"})]),
io:format("~p~n",[encode_ie(#ie_called_context{called_context="called_context"})]),
io:format("~p~n",[encode_ie(#ie_username{username="username"})]),
io:format("~p~n",[encode_ie(#ie_language{language="en"})]),
io:format("~p~n",[encode_ie(#ie_dnid{dnid="693595766"})]),
	io:format("~p~n",[encode_ie(#ie_called_number{called_number="693595766"})]),
	List = [#ie_called_number{called_number="693595766"},#ie_called_context{called_context="test"}],
	IE_Version =#ie_protocol_ver{version=2},
	IE_Called_Number=#ie_called_number{called_number="CalledNum"},
	IE_Calling_Pres=#ie_callingpres{callingpres=allowed_not_screened},
	IE_Calling_Number=#ie_calling_number{calling_number="CallerId"},
	%%TODO add Calling TON and Calling TNS 
	IE_Format=#ie_format{format=speex},
	IE_List=[IE_Version,IE_Called_Number,IE_Calling_Pres,IE_Calling_Number,IE_Format],
	encode_ie_list(IE_List),
%% 	FF=#fullframe{data=IE_List,c=0,dstcallnumber=0,
%% 				  frametype=16#06,iseqno=1,oseqno=0,r=0,srccallnumber=1212,subclass=1,timestamp=2345},
 	FF = #fullframe{srccallnumber=23523,dstcallnumber=0,r=0,c=0,
					timestamp=0,
					oseqno=0,
					iseqno=0,
					frametype=16#06,
					subclass=16#01,
					data = IE_List},
 	Pckt=encode_full_frame(FF).
%% 	{ok,Socket} = gen_udp:open(4569,[{active, false}]),
%% 	gen_udp:send(Socket,"188.116.4.181",4569,Pckt),
%% 	io:format("RECV ~p~n",[gen_udp:recv(Socket, 15000000,10000)]), 
%% 	gen_udp:close(Socket).



generate_test_frame() ->
	List = [#ie_called_number{called_number="693595766"},#ie_called_context{called_context="test"},#ie_username{username="test"}],
	FF=#fullframe{data=List,c=0,dstcallnumber=0,
				  frametype=16#06,iseqno=1,oseqno=0,r=0,srccallnumber=1212,subclass=1,timestamp=2345},
	encode_full_frame(FF).
